home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / usenet / volume4 / bog < prev    next >
Encoding:
Internet Message Format  |  1988-03-10  |  53.4 KB

  1. Path: uunet!husc6!mit-eddie!uw-beaver!tektronix!tekgen!tekred!games-request
  2. From: games-request@tekred.TEK.COM
  3. Newsgroups: comp.sources.games
  4. Subject: v04i001:  bog - the game of boggle
  5. Message-ID: <2273@tekred.TEK.COM>
  6. Date: 10 Mar 88 00:36:23 GMT
  7. Sender: billr@tekred.TEK.COM
  8. Lines: 2480
  9. Approved: billr@tekred.TEK.COM
  10.  
  11. Submitted by: Barry Brachman <uunet!ubc-vision!cs.ubc.ca!brachman>
  12. Comp.sources.games: Volume 4, Issue 1
  13. Archive-name: bog
  14.  
  15.     [I compiled and ran this OK on a Sun 3/60.   -br]
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of shell archive."
  24. # Contents:  README Makefile bog.man bog.h bog.c help.c mach.c mkdict.c
  25. #   mkindex.c prtable.c showdict.c timer.c word.c helpfile
  26. # Wrapped by billr@saab on Tue Mar  1 17:16:48 1988
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f README -a "${1}" != "-c" ; then 
  29.   echo shar: Will not over-write existing file \"README\"
  30. else
  31. echo shar: Extracting \"README\" \(2494 characters\)
  32. sed "s/^X//" >README <<'END_OF_README'
  33. X
  34. XBog is a fairly portable simulation of Parker Brother's game of Boggle and
  35. Xis similar to the 4.[23] BSD "boggle" and Sun's "boggletool".
  36. XBog has not been derived from any proprietary code.
  37. XIt has been tested on the Sun 3 under SunOS 3.2 and on the Atari 1040ST (MWC).
  38. X
  39. XWhat You Need
  40. X
  41. XYou will need curses/termcap and a large word list.
  42. XThe minix word list or /usr/dict/words will do nicely.
  43. XThe word list must already be sorted (you can use "sort -c" to check).
  44. X
  45. XContents
  46. X
  47. X    README        - this file
  48. X    Makefile
  49. X    bog.man        - half-hearted man page (use the game's help command)
  50. X    bog.h        - configuration and header info
  51. X    bog.c        - machine independent game code
  52. X    word.c        - machine independent word list routines
  53. X    help.c        - (curses) help routine
  54. X    mach.c        - (curses) display code
  55. X    prtable.c    - ditto
  56. X    timer.c        - machine dependent (os) input polling
  57. X    mkdict.c    - convert a word list to a bog dictionary
  58. X    mkindex.c    - create an index file for the bog dictionary
  59. X    showdict.c    - print a bog dictionary to stdout
  60. X
  61. XPortability
  62. X
  63. X- I've tried to make bog.c (the program logic) independent of the I/O.
  64. X  My plan was to make it straightforward to adapt the game to run under a
  65. X  windowing system (eg., Suntools, GEM).  I have no plan to actually do this.
  66. X  I've stuck to a small subset of the curses routines.
  67. X- The program runs with the input in raw mode.
  68. X- If you want the running timer you must #define TIMER in bog.h
  69. X  and insert the input polling code in timer.c for your system.  There is
  70. X  already code there for BSD, SYSV, and ATARI.
  71. X
  72. XSetup
  73. X
  74. X1. Check bog.h and Makefile and edit to fit your environment
  75. X2. "make all"
  76. X   This will make all the binaries and create the dictionary and index files
  77. X3. Move "dict", "dict.ind", and "helpfile" to where you specified in bog.h
  78. X4. Play away
  79. X
  80. XDistribution
  81. X
  82. XYou may use this software for your enjoyment and you may share it with others.
  83. XYou may not sell this software or use it for any commercial purposes
  84. Xwhatsoever.  All modified versions of the software that you redistribute must
  85. Xclearly indicate your changes.
  86. X
  87. XIf you come across any bugs or make any changes you'd like to share please
  88. Xsend mail to me rather than posting to the net.
  89. X
  90. XEnjoy. [But beware: boggle can be addictive!]
  91. X
  92. X-----
  93. XBarry Brachman           | {ihnp4!alberta,uw-beaver,uunet}!
  94. XDept. of Computer Science|  ubc-vision!ubc-csgrads!brachman
  95. XUniv. of British Columbia| brachman@grads.cs.ubc.cdn
  96. XVancouver, B.C. V6T 1W5  | brachman%ubc.csnet@csnet-relay.arpa
  97. X(604) 228-4327           | brachman@ubc.csnet
  98. X
  99. END_OF_README
  100. if test 2494 -ne `wc -c <README`; then
  101.     echo shar: \"README\" unpacked with wrong size!
  102. fi
  103. # end of overwriting check
  104. fi
  105. if test -f Makefile -a "${1}" != "-c" ; then 
  106.   echo shar: Will not over-write existing file \"Makefile\"
  107. else
  108. echo shar: Extracting \"Makefile\" \(830 characters\)
  109. sed "s/^X//" >Makefile <<'END_OF_Makefile'
  110. X
  111. X# See bog.h for configuration
  112. X
  113. XOBJS=bog.o help.o mach.o prtable.o timer.o word.o
  114. X
  115. XCFLAGS=-O
  116. XLIBS=-lcurses -ltermlib
  117. X
  118. X# DICT is the dictionary that will be used to construct the word list used
  119. X# by bog
  120. XDICT=/usr/dict/words
  121. X
  122. Xbog: $(OBJS)
  123. X    cc $(CFLAGS) -s -o bog $(OBJS) $(LIBS)
  124. X
  125. Xall: bog mkdict mkindex dict
  126. X
  127. Xmkdict: mkdict.c
  128. X    cc -s -O -o mkdict mkdict.c
  129. X
  130. Xmkindex: mkindex.c
  131. X    cc -s -O -o mkindex mkindex.c
  132. X
  133. Xshowdict: showdict.o word.o
  134. X    cc -s -O -o showdict showdict.o word.o
  135. X    rm -f showdict.o
  136. X
  137. Xdict: mkdict mkindex
  138. X    ./mkdict < $(DICT) > dict
  139. X    ./mkindex < dict > dict.ind
  140. X
  141. X$(OBJS): bog.h
  142. X
  143. Xinstall: all
  144. X    @echo "Move dict, dict.ind, and the helpfile to where you specified in bog.h"
  145. X    @echo "Move bog.man to where you want the manual page to go"
  146. X
  147. Xclean:
  148. X    rm -f *.o bog
  149. X
  150. Xlint:
  151. X    lint -abchx bog.c help.c mach.c prtable.c timer.c word.c
  152. X
  153. END_OF_Makefile
  154. if test 830 -ne `wc -c <Makefile`; then
  155.     echo shar: \"Makefile\" unpacked with wrong size!
  156. fi
  157. # end of overwriting check
  158. fi
  159. if test -f bog.man -a "${1}" != "-c" ; then 
  160.   echo shar: Will not over-write existing file \"bog.man\"
  161. else
  162. echo shar: Extracting \"bog.man\" \(2748 characters\)
  163. sed "s/^X//" >bog.man <<'END_OF_bog.man'
  164. X.TH BOG 1-LOCAL "22 February 1988"
  165. X.UC
  166. X.SH NAME
  167. Xbog \- Word search game
  168. X.SH SYNOPSIS
  169. Xbog [-b] [-d] [-s#] [-t#] [-w#] [+[+]] [boardspec]
  170. X.br
  171. Xmkdict
  172. X.br
  173. Xmkindex
  174. X.SH DESCRIPTION
  175. XThe object of
  176. X.I bog
  177. Xis to find as many words as possible on the Boggle board within the three
  178. Xminute time limit.
  179. XA Boggle board is a four by four arrangement of Boggle cubes, each side of
  180. Xeach cube displaying a letter of the alphabet or `qu'.
  181. XWords are formed by finding a sequence of cubes (letters) that are in the
  182. Xgame's dictionary.
  183. XThe (N+1)th cube in the word must be horizontally,
  184. Xvertically, or diagonally adjacent to the Nth cube.
  185. XCubes cannot be reused.
  186. XWords consist solely of lower case letters and must be at least 3 letters long.
  187. X.PP
  188. XCommand line flags can be given to change the rules of the game.
  189. XThe
  190. X.B +
  191. Xflag allows a cube to be used multiple times, but not in succession.
  192. XThe
  193. X.B ++
  194. Xflag allows the same cubes to be considered adjacent to itself.
  195. X.B
  196. XA seed other than the time of day is specified by
  197. X.B -s#,
  198. Xwhere
  199. X.B #
  200. Xis the seed.
  201. XThe time limit can be changed from the default 3 minutes by using the flag
  202. X.B -t#,
  203. Xwhere
  204. X.B #
  205. Xis the duration (in seconds) of each game.
  206. XThe minimum word length can be changed from 3 letters by specifying
  207. X.B -w#,
  208. Xwhere
  209. X.B #
  210. Xis the minimum number of letters to use.
  211. X.PP
  212. XA starting board position can be specified on the command line by
  213. Xlisting the board left to right and top to bottom.
  214. X.PP
  215. XThe
  216. X.B -b
  217. Xflag puts
  218. X.I bog
  219. Xin batch mode.
  220. XA
  221. X.B boardspec
  222. Xmust also be given.
  223. XThe dictionary is read from stdin and a list of words appearing in
  224. X.B boardspec
  225. Xis printed to stdout.
  226. X.PP
  227. XHelp is available during play by typing `?'.
  228. XMore detailed information on the game is given there.
  229. X.PP
  230. X.I Mkdict
  231. Xreads a word list from stdin, one word per line, and writes a dictionary
  232. Xusable by
  233. X.I bog
  234. Xto stdout.
  235. XThe dictionary is assumed to be sorted.
  236. XImproper words are filtered out.
  237. X.PP
  238. X.I Mkindex
  239. Xreads a dictionary produced by
  240. X.I mkdict
  241. Xfrom stdin
  242. Xand writes an index file usable by
  243. X.I bog
  244. Xto stdout.
  245. X.SH FILES
  246. X.I Bog
  247. Xaccesses a dictionary file, a dictionary index file, and a helpfile.
  248. XLocations are system dependent.
  249. XThe dictionary file must have been created by
  250. X.I mkdict
  251. Xand the index file by
  252. X.I mkindex.
  253. X.SH SEE ALSO
  254. Xboggle(6), boggletool(6)
  255. X.SH BUGS
  256. XIf there are a great many words in the cube the final display of the words
  257. Xmay scroll off of the screen.  (On a 25 line screen about 130 words can be
  258. Xdisplayed.)
  259. X.sp 2
  260. XNo word can contain a 'q' that is not immediately followed by a 'u'.
  261. X.sp 2
  262. XWhen using the '+' or '++' options the display of words found in the board
  263. Xdoesn't indicate reused cubes.
  264. X.SH AUTHOR
  265. XBoggle is a trademark of Parker Brothers.
  266. X.sp 2
  267. XBarry Brachman
  268. X.br
  269. XDept. of Computer Science
  270. X.br
  271. XUniversity of British Columbia
  272. END_OF_bog.man
  273. if test 2748 -ne `wc -c <bog.man`; then
  274.     echo shar: \"bog.man\" unpacked with wrong size!
  275. fi
  276. # end of overwriting check
  277. fi
  278. if test -f bog.h -a "${1}" != "-c" ; then 
  279.   echo shar: Will not over-write existing file \"bog.h\"
  280. else
  281. echo shar: Extracting \"bog.h\" \(1177 characters\)
  282. sed "s/^X//" >bog.h <<'END_OF_bog.h'
  283. X/* vi: set tabstop=4 : */
  284. X
  285. X/*
  286. X * Configuration
  287. X */
  288. X
  289. X#define BSD42            1    /* BSD 4.[23] */
  290. X/* #define ATARI            1    /* Atari ST */
  291. X/* #define SYSV                1    /* System V */
  292. X
  293. X/*
  294. X * If you don't have random() and srandom() #define what you have
  295. X */
  296. X/* #define random            lrand48    /* Sys V */
  297. X/* #define srandom            srand48    /* Sys V */
  298. X
  299. X/* #define random            rand    /* Not good but generally available */
  300. X/* #define srandom(x)        srand((int) x)    /* */
  301. X
  302. X#define TIMER            1    /* Use tty polling (see timer.c) */
  303. X#define LOADDICT        1    /* Load the dictionary for speed */
  304. X
  305. X#define DICT            "/usr/cna/billr/games/bog/dict"
  306. X#define DICTINDEX        "/usr/cna/billr/games/bog/dict.ind"
  307. X#define HELPFILE        "/usr/cna/billr/games/bog/helpfile"
  308. X
  309. X/*
  310. X * The theoretical maximum for MAXWORDLEN is ('a' - 1) == 96
  311. X */
  312. X#define MAXWORDLEN        40
  313. X#define MAXPWORDS        200
  314. X#define MAXMWORDS        200
  315. X#define MAXPSPACE        2000
  316. X#define MAXMSPACE        4000
  317. X
  318. X#define MAXCOLS            20
  319. X
  320. X#define PROMPT_COL        20
  321. X#define PROMPT_LINE        2
  322. X
  323. X#define BOARD_COL        0
  324. X#define BOARD_LINE        0
  325. X
  326. X#define SCORE_COL        20
  327. X#define SCORE_LINE        0
  328. X
  329. X#define LIST_COL        0
  330. X#define LIST_LINE        10
  331. X
  332. X#define TIMER_COL        20
  333. X#define TIMER_LINE        2
  334. X
  335. Xstruct dictindex {
  336. X    long start;
  337. X    long length;
  338. X};
  339. X
  340. END_OF_bog.h
  341. if test 1177 -ne `wc -c <bog.h`; then
  342.     echo shar: \"bog.h\" unpacked with wrong size!
  343. fi
  344. # end of overwriting check
  345. fi
  346. if test -f bog.c -a "${1}" != "-c" ; then 
  347.   echo shar: Will not over-write existing file \"bog.c\"
  348. else
  349. echo shar: Extracting \"bog.c\" \(13598 characters\)
  350. sed "s/^X//" >bog.c <<'END_OF_bog.c'
  351. X/* vi: set tabstop=4 : */
  352. X
  353. X#include "bog.h"
  354. X
  355. X#include <ctype.h>
  356. X#include <stdio.h>
  357. X
  358. Xchar *version[] = "bog V1.0 brachman@ubc.csnet 23-Feb-88";
  359. X
  360. Xstruct dictindex dictindex[26];
  361. X
  362. X/*
  363. X * Cube position numbering:
  364. X *
  365. X *    0 1 2 3
  366. X *    4 5 6 7
  367. X *    8 9 A B
  368. X *    C D E F
  369. X */
  370. Xstatic int adjacency[16][16] = {
  371. X/*    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F */
  372. X    { 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },        /* 0 */
  373. X    { 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },        /* 1 */
  374. X    { 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },        /* 2 */
  375. X    { 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },        /* 3 */
  376. X    { 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },        /* 4 */
  377. X    { 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0 },        /* 5 */
  378. X    { 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0 },        /* 6 */
  379. X    { 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0 },        /* 7 */
  380. X    { 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0 },        /* 8 */
  381. X    { 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0 },        /* 9 */
  382. X    { 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1 },        /* A */
  383. X    { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1 },        /* B */
  384. X    { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0 },        /* C */
  385. X    { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0 },        /* D */
  386. X    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1 },        /* E */
  387. X    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 }        /* F */
  388. X};
  389. X
  390. Xstatic int letter_map[26][16];
  391. X
  392. Xchar board[17];
  393. Xint wordpath[MAXWORDLEN + 1];
  394. Xint wordlen;        /* Length of last word returned by nextword() */
  395. Xint usedbits;
  396. X
  397. Xchar *pword[MAXPWORDS], pwords[MAXPSPACE], *pwordsp;
  398. Xint npwords;
  399. X
  400. Xchar *mword[MAXMWORDS], mwords[MAXMSPACE], *mwordsp;
  401. Xint nmwords;
  402. X
  403. Xint ngames = 0;
  404. Xint tnmwords = 0, tnpwords = 0;
  405. X
  406. X#ifdef TIMER
  407. X#include <setjmp.h>
  408. X
  409. Xjmp_buf env;
  410. X#endif TIMER
  411. X
  412. Xlong start_t;
  413. X
  414. Xstatic FILE *dictfp = (FILE *) NULL;
  415. X
  416. Xint batch;
  417. Xint debug;
  418. Xint minlength;
  419. Xint reuse;
  420. Xint tlimit;
  421. X
  422. Xchar *batchword(), *getline();
  423. X
  424. Xmain(argc, argv)
  425. Xint argc;
  426. Xchar **argv;
  427. X{
  428. X    int done, i, selfuse;
  429. X    char *bspec, *p;
  430. X    long t;
  431. X    long atol();
  432. X    FILE *opendict();
  433. X
  434. X    debug = 0;
  435. X    bspec = (char *) NULL;
  436. X    reuse = 0;
  437. X    batch = 0;
  438. X    selfuse = 0;
  439. X    minlength = 3;
  440. X    tlimit = 180;        /* 3 minutes is standard */
  441. X    time(&t);
  442. X
  443. X    for (i = 1; i < argc; i++) {
  444. X        if (argv[i][0] == '-') {
  445. X            switch (argv[i][1]) {
  446. X            case 'b':
  447. X                batch = 1;
  448. X                break;
  449. X            case 'd':
  450. X                debug = 1;
  451. X                break;
  452. X            case 's':
  453. X                t = atol(&argv[i][2]);
  454. X                break;
  455. X            case 't':
  456. X                if ((tlimit = atoi(&argv[i][2])) < 1) {
  457. X                    (void) fprintf(stderr, "Bad time limit\n");
  458. X                    exit(1);
  459. X                }
  460. X                break;
  461. X            case 'w':
  462. X                if ((minlength = atoi(&argv[i][2])) < 3) {
  463. X                    (void) fprintf(stderr, "Min word length must be > 2\n");
  464. X                    exit(1);
  465. X                }
  466. X                break;
  467. X            default:
  468. X                usage();
  469. X                /*NOTREACHED*/
  470. X            }
  471. X        }
  472. X        else if (strcmp(argv[i], "+") == 0)
  473. X            reuse = 1;
  474. X        else if (strcmp(argv[i], "++") == 0)
  475. X            selfuse = 1;
  476. X        else if (islower(argv[i][0])) {
  477. X            if (strlen(argv[i]) != 16) {
  478. X                usage();
  479. X                /*NOTREACHED*/
  480. X            }
  481. X            /* This board is assumed to be valid... */
  482. X            bspec = argv[i];
  483. X        }
  484. X        else {
  485. X            usage();
  486. X            /*NOREACHED*/
  487. X        }
  488. X    }
  489. X
  490. X    if (batch && bspec == (char *) NULL) {
  491. X        (void) fprintf(stderr, "Must give both -b and a board setup\n");
  492. X        exit(1);
  493. X    }
  494. X
  495. X    if (selfuse) {
  496. X        for (i = 0; i < 16; i++)
  497. X            adjacency[i][i] = 1;
  498. X    }
  499. X
  500. X    if (batch) {
  501. X        newgame(bspec);
  502. X        while ((p = batchword(stdin)) != (char *) NULL)
  503. X            (void) printf("%s\n", p);
  504. X    }
  505. X    else {
  506. X        if (debug)
  507. X            (void) printf("seed = %ld\n", t);
  508. X        setup();
  509. X        prompt("Loading the dictionary...");
  510. X        if ((dictfp = opendict(DICT)) == (FILE *) NULL) {
  511. X            (void) fprintf(stderr, "Can't load %s\n", DICT);
  512. X            cleanup();
  513. X            exit(1);
  514. X        }
  515. X#ifdef LOADDICT
  516. X        if (loaddict(dictfp) < 0) {
  517. X            (void) fprintf(stderr, "Can't load %s\n", DICT);
  518. X            cleanup();
  519. X            exit(1);
  520. X        }
  521. X        (void) fclose(dictfp);
  522. X        dictfp = (FILE *) NULL;
  523. X#endif
  524. X        if (loadindex(DICTINDEX) < 0) {
  525. X            (void) fprintf(stderr, "Can't load %s\n", DICTINDEX);
  526. X            cleanup();
  527. X            exit(1);
  528. X        }
  529. X        srandom(t);
  530. X
  531. X        prompt("Type <space> to begin...");
  532. X        while (inputch() != ' ')
  533. X            ;
  534. X
  535. X        done = 0;
  536. X        while (!done) {
  537. X            newgame(bspec);
  538. X            bspec = (char *) NULL;        /* reset for subsequent games */
  539. X            playgame();
  540. X            prompt("Type <space> to continue, any cap to quit...");
  541. X            flushin(stdin);
  542. X            while (1) {
  543. X                int ch;
  544. X
  545. X                ch = inputch();
  546. X                if (ch == '\033')
  547. X                    findword();
  548. X                else {
  549. X                    if (isupper(ch)) {
  550. X                        done = 1;
  551. X                        break;
  552. X                    }
  553. X                    if (ch == ' ')
  554. X                        break;
  555. X                }
  556. X            }
  557. X        }
  558. X        cleanup();
  559. X    }
  560. X    exit(0);
  561. X}
  562. X
  563. X/*
  564. X * Read a line from the given stream and check if it is legal
  565. X * Return a pointer to a legal word or a null pointer when EOF is reached
  566. X */
  567. Xchar *
  568. Xbatchword(fp)
  569. XFILE *fp;
  570. X{
  571. X    register int *p, *q;
  572. X    register char *w;
  573. X    char *nextword();
  574. X
  575. X    q = &wordpath[MAXWORDLEN + 1];
  576. X    p = wordpath;
  577. X    while (p < q)
  578. X        *p++ = -1;
  579. X    while ((w = nextword(fp)) != (char *) NULL) {
  580. X        if (wordlen < minlength)
  581. X            continue;
  582. X        p = wordpath;
  583. X        while (p < q && *p != -1)
  584. X            *p++ = -1;
  585. X        usedbits = 0;
  586. X        if (checkword(w, -1, wordpath) != -1)
  587. X            return(w);
  588. X    }
  589. X    return((char *) NULL);
  590. X}
  591. X
  592. X/*
  593. X * Play a single game
  594. X * Reset the word lists from last game
  595. X * Keep track of the running stats
  596. X */
  597. Xplaygame()
  598. X{
  599. X    /* Can't use register variables if setjmp() is used! */
  600. X    int i, *p, *q;
  601. X    long t;
  602. X    char buf[MAXWORDLEN + 1];
  603. X    int compar();
  604. X
  605. X    ngames++;
  606. X    npwords = 0;
  607. X    pwordsp = pwords;
  608. X    nmwords = 0;
  609. X    mwordsp = mwords;
  610. X
  611. X    time(&start_t);
  612. X
  613. X    q = &wordpath[MAXWORDLEN + 1];
  614. X    p = wordpath;
  615. X    while (p < q)
  616. X        *p++ = -1;
  617. X    showboard(board);
  618. X    startwords();
  619. X    if (setjmp(env)) {
  620. X        badword();
  621. X        goto timesup;
  622. X    }
  623. X
  624. X    while (1) {
  625. X        if (getline(buf) == (char *) NULL) {
  626. X            if (feof(stdin))
  627. X                clearerr(stdin);
  628. X            break;
  629. X        }
  630. X        time(&t);
  631. X        if (t - start_t >= tlimit) {
  632. X            badword();
  633. X            break;
  634. X        }
  635. X        if (buf[0] == '\0') {
  636. X            int remaining;
  637. X
  638. X            remaining = tlimit - (int) (t - start_t);
  639. X            (void) sprintf(buf, "%d:%02d", remaining / 60, remaining % 60);
  640. X            showstr(buf, 1);
  641. X            continue;
  642. X        }
  643. X        if (strlen(buf) < minlength) {
  644. X            badword();
  645. X            continue;
  646. X        }
  647. X
  648. X        p = wordpath;
  649. X        while (p < q && *p != -1)
  650. X            *p++ = -1;
  651. X        usedbits = 0;
  652. X
  653. X        if (checkword(buf, -1, wordpath) < 0)
  654. X            badword();
  655. X        else {
  656. X            if (debug) {
  657. X                (void) printf("[");
  658. X                for (i = 0; wordpath[i] != -1; i++)
  659. X                    (void) printf(" %d", wordpath[i]);
  660. X                (void) printf(" ]\n");
  661. X            }
  662. X            for (i = 0; i < npwords; i++) {
  663. X                if (strcmp(pword[i], buf) == 0)
  664. X                    break;
  665. X            }
  666. X            if (i != npwords) {            /* already used the word */
  667. X                badword();
  668. X                showword(i);
  669. X            }
  670. X            else if (!validword(buf))
  671. X                badword();
  672. X            else {
  673. X                int len;
  674. X
  675. X                len = strlen(buf) + 1;
  676. X                if (npwords == MAXPWORDS - 1 ||
  677. X                        pwordsp + len >= &pwords[MAXPSPACE]) {
  678. X                    (void) fprintf(stderr, "Too many words!\n");
  679. X                    cleanup();
  680. X                    exit(1);
  681. X                }
  682. X                pword[npwords++] = pwordsp;
  683. X                (void) strcpy(pwordsp, buf);
  684. X                pwordsp += len;
  685. X                addword(buf);
  686. X            }
  687. X        }
  688. X    }
  689. X
  690. Xtimesup: ;
  691. X
  692. X    /*
  693. X     * Sort the player's words and terminate the list with a null
  694. X     * entry to help out checkdict()
  695. X     */
  696. X    qsort(pword, npwords, sizeof(pword[0]), compar);
  697. X    pword[npwords] = (char *) NULL;
  698. X
  699. X    /*
  700. X     * These words don't need to be sorted since the dictionary is sorted
  701. X     */
  702. X    checkdict();
  703. X
  704. X    tnmwords += nmwords;
  705. X    tnpwords += npwords;
  706. X
  707. X    results();
  708. X}
  709. X
  710. X/*
  711. X * Check if the given word is present on the board, with the constraint
  712. X * that the first letter of the word is adjacent to square 'prev'
  713. X * Keep track of the current path of squares for the word
  714. X * A 'q' must be followed by a 'u'
  715. X * Words must end with a null
  716. X * Return 1 on success, -1 on failure
  717. X */
  718. Xcheckword(word, prev, path)
  719. Xchar *word;
  720. Xint prev, *path;
  721. X{
  722. X    register char *p, *q;
  723. X    register int i, *lm;
  724. X
  725. X    if (debug) {
  726. X        (void) printf("checkword(%s, %d, [", word, prev);
  727. X            for (i = 0; wordpath[i] != -1; i++)
  728. X                (void) printf(" %d", wordpath[i]);
  729. X            (void) printf(" ]\n");
  730. X    }
  731. X
  732. X    if (*word == '\0')
  733. X        return(1);
  734. X
  735. X    lm = letter_map[*word - 'a'];
  736. X
  737. X    if (prev == -1) {
  738. X        char subword[MAXWORDLEN + 1];
  739. X
  740. X        /*
  741. X         * Check for letters not appearing in the cube to eliminate some
  742. X         * recursive calls
  743. X         * Fold 'qu' into 'q'
  744. X         */
  745. X        p = word;
  746. X        q = subword;
  747. X        while (*p != '\0') {
  748. X            if (*letter_map[*p - 'a'] == -1)
  749. X                return(-1);
  750. X            *q++ = *p;
  751. X            if (*p++ == 'q') {
  752. X                if (*p++ != 'u')
  753. X                    return(-1);
  754. X            }
  755. X        }
  756. X        *q = '\0';
  757. X        while (*lm != -1) {
  758. X            *path = *lm;
  759. X            usedbits |= (1 << *lm);
  760. X            if (checkword(subword + 1, *lm, path + 1) > 0)
  761. X                return(1);
  762. X            usedbits &= ~(1 << *lm);
  763. X            lm++;
  764. X        }
  765. X        return(-1);
  766. X    }
  767. X
  768. X    /*
  769. X     * A cube is only adjacent to itself in the adjacency matrix if selfuse
  770. X     * was set, so a cube can't be used twice in succession if only the reuse
  771. X     * flag is set
  772. X     */
  773. X    for (i = 0; lm[i] != -1; i++) {
  774. X        if (adjacency[prev][lm[i]]) {
  775. X            int used;
  776. X
  777. X            used = 1 << lm[i];
  778. X            /* If necessary, check if the square has already been used */
  779. X            if (!reuse && (usedbits & used))
  780. X                    continue;
  781. X            *path = lm[i];
  782. X            usedbits |= used;
  783. X            if (checkword(word + 1, lm[i], path + 1) > 0)
  784. X                return(1);
  785. X            usedbits &= ~used;
  786. X        }
  787. X    }
  788. X    *path = -1;        /* in case of a backtrack */
  789. X    return(-1);
  790. X}
  791. X
  792. X/*
  793. X * A word is invalid if it is not in the dictionary
  794. X * At this point it is already known that the word can be formed from
  795. X * the current board
  796. X */
  797. Xvalidword(word)
  798. Xchar *word;
  799. X{
  800. X    register int j;
  801. X    register char *q, *w;
  802. X    char *nextword();
  803. X
  804. X    j = word[0] - 'a';
  805. X    if (dictseek(dictfp, dictindex[j].start, 0) < 0) {
  806. X        (void) fprintf(stderr, "Seek error\n");
  807. X        cleanup();
  808. X        exit(1);
  809. X    }
  810. X
  811. X    while ((w = nextword(dictfp)) != (char *) NULL) {
  812. X        int ch;
  813. X
  814. X        if (*w != word[0])    /* end of words starting with word[0] */
  815. X            break;
  816. X        q = word;
  817. X        while ((ch = *w++) == *q++ && ch != '\0')
  818. X            ;
  819. X        if (*(w - 1) == '\0' && *(q - 1) == '\0')
  820. X            return(1);
  821. X    }
  822. X    if (dictfp != (FILE *) NULL && feof(dictfp))    /* Special case for z's */
  823. X        clearerr(dictfp);
  824. X    return(0);
  825. X}
  826. X
  827. X/*
  828. X * Check each word in the dictionary against the board
  829. X * Delete words from the machine list that the player has found
  830. X * Assume both the dictionary and the player's words are already sorted
  831. X */
  832. Xcheckdict()
  833. X{
  834. X    register char *p, **pw, *w;
  835. X    register int i;
  836. X    int prevch, previndex, *pi, *qi, st;
  837. X
  838. X    mwordsp = mwords;
  839. X    nmwords = 0;
  840. X    pw = pword;
  841. X    prevch ='a';
  842. X    qi = &wordpath[MAXWORDLEN + 1];
  843. X
  844. X    (void) dictseek(dictfp, 0L, 0);
  845. X    while ((w = nextword(dictfp)) != (char *) NULL) {
  846. X        if (wordlen < minlength)
  847. X            continue;
  848. X        if (*w != prevch) {
  849. X            /*
  850. X             * If we've moved on to a word with a different first letter
  851. X             * then we can speed things up by skipping all words starting
  852. X             * with a letter that doesn't appear in the cube
  853. X             */
  854. X            i = (int) (*w - 'a');
  855. X            while (i < 26 && letter_map[i][0] == -1)
  856. X                i++;
  857. X            if (i == 26)
  858. X                break;
  859. X            previndex = prevch - 'a';
  860. X            prevch = i + 'a';
  861. X            /*
  862. X             * Fall through if the word's first letter appears in the cube
  863. X             * (i.e., if we can't skip ahead), otherwise seek to the
  864. X             * beginning of words in the dictionary starting with the
  865. X             * next letter (alphabetically) appearing in the cube and then
  866. X             * read the first word
  867. X             */
  868. X            if (i != previndex + 1) {
  869. X                if (dictseek(dictfp, dictindex[i].start, 0) < 0) {
  870. X                    (void) fprintf(stderr, "Seek error in checkdict()\n");
  871. X                    cleanup();
  872. X                    exit(1);
  873. X                }
  874. X                continue;
  875. X            }
  876. X        }
  877. X
  878. X        pi = wordpath;
  879. X        while (pi < qi && *pi != -1)
  880. X            *pi++ = -1;
  881. X        usedbits = 0;
  882. X        if (checkword(w, -1, wordpath) == -1)
  883. X            continue;
  884. X
  885. X        st = 1;
  886. X        while (*pw != (char *) NULL && (st = strcmp(*pw, w)) < 0)
  887. X            pw++;
  888. X        if (st == 0)            /* found it */
  889. X            continue;
  890. X        if (nmwords == MAXMWORDS ||
  891. X                    mwordsp + wordlen + 1 >= &mwords[MAXMSPACE]) {
  892. X            (void) fprintf(stderr, "Too many words!\n");
  893. X            cleanup();
  894. X            exit(1);
  895. X        }
  896. X        mword[nmwords++] = mwordsp;
  897. X        p = w;
  898. X        while (*mwordsp++ = *p++)
  899. X            ;
  900. X    }
  901. X}
  902. X
  903. X/*
  904. X * Crank up a new game
  905. X * If the argument is non-null then it is assumed to be a legal board spec
  906. X * in ascending cube order, oth. make a random board
  907. X */
  908. Xnewgame(b)
  909. Xchar *b;
  910. X{
  911. X    register int i, p, q;
  912. X    char *tmp;
  913. X    int *lm[26];
  914. X    long random();
  915. X    static char *cubes[16] = {
  916. X        "ednosw", "aaciot", "acelrs", "ehinps",
  917. X        "eefhiy", "elpstu", "acdemp", "gilruw",
  918. X        "egkluy", "ahmors", "abilty", "adenvz",
  919. X        "bfiorx", "dknotu", "abjmoq", "egintv"
  920. X    };
  921. X
  922. X    if (b == (char *) NULL) {
  923. X        /*
  924. X         * Shake the cubes and make the board
  925. X         */
  926. X        i = 0;
  927. X        while (i < 100) {
  928. X            p = (int) (random() % 16);
  929. X            q = (int) (random() % 16);
  930. X            if (p != q) {
  931. X                tmp = cubes[p];
  932. X                cubes[p] = cubes[q];
  933. X                cubes[q] = tmp;
  934. X                i++;
  935. X            }
  936. X            /* else try again */
  937. X        }
  938. X
  939. X        for (i = 0; i < 16; i++)
  940. X            board[i] = cubes[i][random() % 6];
  941. X    }
  942. X    else {
  943. X        for (i = 0; i < 16; i++)
  944. X            board[i] = b[i];
  945. X    }
  946. X    board[16] = '\0';
  947. X
  948. X    /*
  949. X     * Set up the map from letter to location(s)
  950. X     * Each list is terminated by a -1 entry
  951. X     */
  952. X    for (i = 0; i < 26; i++) {
  953. X        lm[i] = letter_map[i];
  954. X        *lm[i] = -1;
  955. X    }
  956. X
  957. X    for (i = 0; i < 16; i++) {
  958. X        register int j;
  959. X
  960. X        j = (int) (board[i] - 'a');
  961. X        *lm[j] = i;
  962. X        *(++lm[j]) = -1;
  963. X    }
  964. X
  965. X    if (debug) {
  966. X        for (i = 0; i < 26; i++) {
  967. X            int ch, j;
  968. X
  969. X            (void) printf("%c:", 'a' + i);
  970. X            for (j = 0; (ch = letter_map[i][j]) != -1; j++)
  971. X                (void) printf(" %d", ch);
  972. X            (void) printf("\n");
  973. X        }
  974. X    }
  975. X
  976. X}
  977. X
  978. Xcompar(p, q)
  979. Xchar **p, **q;
  980. X{
  981. X    return(strcmp(*p, *q));
  982. X}
  983. X
  984. Xusage()
  985. X{
  986. X(void) fprintf(stderr,
  987. X"Usage: bog [-b] [-d] [-s#] [-t#] [-w#] [+[+]] [boardspec]\n");
  988. X(void) fprintf(stderr, "-b: 'batch mode' (boardspec must be present)\n");
  989. X(void) fprintf(stderr, "-d: debug\n");
  990. X(void) fprintf(stderr, "-s#: use # as the random number seed\n");
  991. X(void) fprintf(stderr, "-t#: time limit is # seconds\n");
  992. X(void) fprintf(stderr, "-w#: minimum word length is # letters\n");
  993. X(void) fprintf(stderr, "+: can reuse a cube, but not twice in succession\n");
  994. X(void) fprintf(stderr, "++: can reuse cubes arbitrarily\n");
  995. X(void) fprintf(stderr, "boardspec: the first board to use (use 'q' for 'qu')\n");
  996. X    exit(1);
  997. X}
  998. X
  999. END_OF_bog.c
  1000. if test 13598 -ne `wc -c <bog.c`; then
  1001.     echo shar: \"bog.c\" unpacked with wrong size!
  1002. fi
  1003. # end of overwriting check
  1004. fi
  1005. if test -f help.c -a "${1}" != "-c" ; then 
  1006.   echo shar: Will not over-write existing file \"help.c\"
  1007. else
  1008. echo shar: Extracting \"help.c\" \(1149 characters\)
  1009. sed "s/^X//" >help.c <<'END_OF_help.c'
  1010. X/* vi: set tabstop=4 : */
  1011. X
  1012. X#include <curses.h>
  1013. X#include <stdio.h>
  1014. X
  1015. X#include "bog.h"
  1016. X
  1017. Xhelp()
  1018. X{
  1019. X    int eof, i;
  1020. X    FILE *fp;
  1021. X    WINDOW *win;
  1022. X    char buf[BUFSIZ];
  1023. X    extern int ncols, nlines;
  1024. X
  1025. X    if ((fp = fopen(HELPFILE, "r")) == (FILE *) NULL)
  1026. X        return(-1);
  1027. X    win = newwin(0, 0, 0, 0);
  1028. X    clearok(win, 1);
  1029. X
  1030. X    eof = 0;
  1031. X    if (ungetc(getc(fp), fp) == EOF) {
  1032. X        wprintw(win, "There doesn't seem to be any help.");
  1033. X        eof = 1;            /* Nothing there... */
  1034. X    }
  1035. X
  1036. X    while (!eof) {
  1037. X        for (i = 0; i < nlines - 3; i++) {
  1038. X            if (fgets(buf, sizeof(buf), fp) == (char *) NULL) {
  1039. X                eof = 1;
  1040. X                break;
  1041. X            }
  1042. X            if (buf[0] == '.' && buf[1] == '\n')
  1043. X                break;
  1044. X            wprintw(win, "%s", buf);
  1045. X        }
  1046. X        if (eof || ungetc(getc(fp), fp) == EOF) {
  1047. X            eof = 1;
  1048. X            break;
  1049. X        }
  1050. X        wmove(win, nlines - 1, 0);
  1051. X        wprintw(win, "Type <space> to continue, anything else to quit...");
  1052. X        wrefresh(win);
  1053. X        if ((inputch() & 0177) != ' ')
  1054. X            break;
  1055. X        wclear(win);
  1056. X    }
  1057. X
  1058. X    fclose(fp);
  1059. X    if (eof) {
  1060. X        extern char *version;
  1061. X
  1062. X        wprintw(win, "%s", version);
  1063. X        wmove(win, nlines - 1, 0);
  1064. X        wprintw(win, "Hit any key to continue...");
  1065. X        wrefresh(win);
  1066. X        inputch();
  1067. X    }
  1068. X    delwin(win);
  1069. X    clearok(stdscr, 1);
  1070. X    refresh();
  1071. X    return(0);
  1072. X}
  1073. X
  1074. END_OF_help.c
  1075. if test 1149 -ne `wc -c <help.c`; then
  1076.     echo shar: \"help.c\" unpacked with wrong size!
  1077. fi
  1078. # end of overwriting check
  1079. fi
  1080. if test -f mach.c -a "${1}" != "-c" ; then 
  1081.   echo shar: Will not over-write existing file \"mach.c\"
  1082. else
  1083. echo shar: Extracting \"mach.c\" \(10502 characters\)
  1084. sed "s/^X//" >mach.c <<'END_OF_mach.c'
  1085. X/* vi: set tabstop=4 : */
  1086. X
  1087. X/*
  1088. X * Terminal interface
  1089. X *
  1090. X * Input is raw and unechoed
  1091. X */
  1092. X
  1093. X#ifdef unix
  1094. X#include <sgtty.h>
  1095. X#endif
  1096. X#include <signal.h>
  1097. X#include <curses.h>
  1098. X#include <ctype.h>
  1099. X#include <stdio.h>
  1100. X
  1101. X#include "bog.h"
  1102. X
  1103. Xstatic int ccol, crow, maxw;
  1104. Xstatic int colstarts[MAXCOLS], ncolstarts;
  1105. Xstatic int lastline;
  1106. Xint ncols, nlines;
  1107. X
  1108. X/*
  1109. X * Do system dependent initialization
  1110. X * This is called once, when the program starts
  1111. X */
  1112. Xsetup()
  1113. X{
  1114. X
  1115. X    if (tty_setup() < 0)
  1116. X        return(-1);
  1117. X    return(0);
  1118. X}
  1119. X
  1120. X/*
  1121. X * Do system dependent clean up
  1122. X * This is called once, just before the program terminates
  1123. X */
  1124. Xcleanup()
  1125. X{
  1126. X
  1127. X    tty_cleanup();
  1128. X}
  1129. X
  1130. X/*
  1131. X * Display the player's word list, the list of words not found, and the running
  1132. X * stats
  1133. X */
  1134. Xresults()
  1135. X{
  1136. X    int col, row;
  1137. X    int denom1, denom2;
  1138. X    extern int ngames, nmwords, npwords, tnmwords, tnpwords;
  1139. X    extern char *pword[], *mword[];
  1140. X    int prwidth(), prword();
  1141. X
  1142. X    move(LIST_LINE, LIST_COL);
  1143. X    clrtobot();
  1144. X    printw("Words you found (%d):", npwords);
  1145. X    refresh();
  1146. X    move(LIST_LINE + 1, LIST_COL);
  1147. X    prtable(pword, npwords, 0, ncols, prword, prwidth);
  1148. X
  1149. X    getyx(stdscr, row, col);
  1150. X    move(row + 1, col);
  1151. X    printw("Words you missed (%d):", nmwords);
  1152. X    refresh();
  1153. X    move(row + 2, col);
  1154. X    prtable(mword, nmwords, 0, ncols, prword, prwidth);
  1155. X
  1156. X    denom1 = npwords + nmwords;
  1157. X    denom2 = tnpwords + tnmwords;
  1158. X    move(SCORE_LINE, SCORE_COL);
  1159. X    printw("Percentage: %0.2f%% (%0.2f%% over %d game%s)\n",
  1160. X        denom1 ? (100.0 * npwords) / (double) (npwords + nmwords) : 0.0,
  1161. X        denom2 ? (100.0 * tnpwords) / (double) (tnpwords + tnmwords) : 0.0,
  1162. X        ngames, ngames > 1 ? "s" : "");
  1163. X}
  1164. X
  1165. Xstatic
  1166. Xprword(base, index)
  1167. Xchar **base;
  1168. Xint index;
  1169. X{
  1170. X    printw("%s", base[index]);
  1171. X}
  1172. X
  1173. Xstatic
  1174. Xprwidth(base, index)
  1175. Xchar **base;
  1176. Xint index;
  1177. X{
  1178. X
  1179. X    return(strlen(base[index]));
  1180. X}
  1181. X
  1182. X/*
  1183. X * Main input routine
  1184. X *
  1185. X * - doesn't accept words longer than MAXWORDLEN or containing caps
  1186. X */
  1187. Xchar *
  1188. Xgetline(q)
  1189. Xchar *q;
  1190. X{
  1191. X    register int ch, done;
  1192. X    register char *p;
  1193. X    int row, col;
  1194. X
  1195. X    p = q;
  1196. X    done = 0;
  1197. X    while (!done) {
  1198. X        ch = rawch();
  1199. X        switch (ch) {
  1200. X        case '\n':
  1201. X        case '\r':
  1202. X        case ' ':
  1203. X            done = 1;
  1204. X            break;
  1205. X        case '\033':
  1206. X            findword();
  1207. X            break;
  1208. X        case '\177':            /* <del> */
  1209. X        case '\010':            /* <bs> */
  1210. X            if (p == q)
  1211. X                break;
  1212. X            p--;
  1213. X            getyx(stdscr, row, col);
  1214. X            move(row, col - 1);
  1215. X            clrtoeol();
  1216. X            refresh();
  1217. X            break;
  1218. X        case '\025':            /* <^u> */
  1219. X        case '\027':            /* <^w> */
  1220. X            if (p == q)
  1221. X                break;
  1222. X            getyx(stdscr, row, col);
  1223. X            move(row, col - (int) (p - q));
  1224. X            p = q;
  1225. X            clrtoeol();
  1226. X            refresh();
  1227. X            break;
  1228. X#ifdef SIGTSTP
  1229. X        case '\032':            /* <^z> */
  1230. X            stop_catcher();
  1231. X            break;
  1232. X#endif
  1233. X        case '\023':            /* <^s> */
  1234. X            stoptime();
  1235. X            printw("<PAUSE>");
  1236. X            refresh();
  1237. X            while ((ch = inputch()) != '\021' && ch != '\023')
  1238. X                ;
  1239. X            move(crow, ccol);
  1240. X            clrtoeol();
  1241. X            refresh();
  1242. X            starttime();
  1243. X            break;
  1244. X        case '\003':            /* <^c> */
  1245. X            cleanup();
  1246. X            exit(0);
  1247. X            /*NOTREACHED*/
  1248. X        case '\004':            /* <^d> */
  1249. X            done = 1;
  1250. X            ch = EOF;
  1251. X            break;
  1252. X        case '\014':            /* <^l> */
  1253. X        case '\022':            /* <^r> */
  1254. X            clearok(stdscr, 1);
  1255. X            refresh();
  1256. X            break;
  1257. X        case '?':
  1258. X            stoptime();
  1259. X            if (help() < 0)
  1260. X                showstr("Can't open help file", 1);
  1261. X            starttime();
  1262. X            break;
  1263. X        default:
  1264. X            if (!islower(ch))
  1265. X                break;
  1266. X            if ((int) (p - q) == MAXWORDLEN) {
  1267. X                p = q;
  1268. X                badword();
  1269. X                break;
  1270. X            }
  1271. X            *p++ = ch;
  1272. X            addch(ch);
  1273. X            refresh();
  1274. X            break;
  1275. X        }
  1276. X    }
  1277. X    *p = '\0';
  1278. X    if (ch == EOF)
  1279. X        return((char *) NULL);
  1280. X    return(q);
  1281. X}
  1282. X
  1283. Xinputch()
  1284. X{
  1285. X
  1286. X    return(getch() & 0177);
  1287. X}
  1288. X
  1289. X#ifdef XXX
  1290. X/*
  1291. X * Flush all pending input
  1292. X */
  1293. Xflushin(fp)
  1294. XFILE *fp;
  1295. X{
  1296. X
  1297. X    flushinp();
  1298. X}
  1299. X#endif XXX
  1300. X
  1301. X#ifdef TIOCFLUSH
  1302. X#include <sys/file.h>
  1303. X
  1304. Xflushin(fp)
  1305. XFILE *fp;
  1306. X{
  1307. X    int arg;
  1308. X
  1309. X    arg = FREAD;
  1310. X    (void) ioctl(fileno(fp), TIOCFLUSH, &arg);
  1311. X}
  1312. X#endif TIOCFLUSH
  1313. X
  1314. X#ifdef ATARI
  1315. X#include <osbind.h>
  1316. X
  1317. X/*ARGSUSED*/
  1318. Xflushin(fp)
  1319. XFILE *fp;
  1320. X{
  1321. X
  1322. X    while (Cconis() == -1)
  1323. X        ;
  1324. X}
  1325. X#endif ATARI
  1326. X
  1327. Xstatic int gone;
  1328. X
  1329. X/*
  1330. X * Stop the game timer
  1331. X */
  1332. Xstoptime()
  1333. X{
  1334. X    long t;
  1335. X    extern long start_t;
  1336. X
  1337. X    time(&t);
  1338. X    gone = (int) (t - start_t);
  1339. X}
  1340. X
  1341. X/*
  1342. X * Restart the game timer
  1343. X */
  1344. Xstarttime()
  1345. X{
  1346. X    long t;
  1347. X    extern long start_t;
  1348. X
  1349. X    time(&t);
  1350. X    start_t = t - (long) gone;
  1351. X}
  1352. X
  1353. X/*
  1354. X * Initialize for the display of the player's words as they are typed
  1355. X * This display starts at (LIST_LINE, LIST_COL) and goes "down" until the last
  1356. X * line.  After the last line a new column is started at LIST_LINE
  1357. X * Keep track of each column position for showword()
  1358. X * There is no check for exceeding COLS
  1359. X */
  1360. Xstartwords()
  1361. X{
  1362. X
  1363. X    crow = LIST_LINE;
  1364. X    ccol = LIST_COL;
  1365. X    maxw = 0;
  1366. X    ncolstarts = 1;
  1367. X    colstarts[0] = LIST_COL;
  1368. X    move(LIST_LINE, LIST_COL);
  1369. X    refresh();
  1370. X}
  1371. X
  1372. X/*
  1373. X * Add a word to the list and start a new column if necessary
  1374. X * The maximum width of the current column is maintained so we know where
  1375. X * to start the next column
  1376. X */
  1377. Xaddword(w)
  1378. Xchar *w;
  1379. X{
  1380. X    int n;
  1381. X
  1382. X    if (crow == lastline) {
  1383. X        crow = LIST_LINE;
  1384. X        ccol += (maxw + 5);
  1385. X        colstarts[ncolstarts++] = ccol;
  1386. X        maxw = 0;
  1387. X        move(crow, ccol);
  1388. X    }
  1389. X    else {
  1390. X        move(++crow, ccol);
  1391. X        if ((n = strlen(w)) > maxw)
  1392. X            maxw = n;
  1393. X    }
  1394. X    refresh();
  1395. X}
  1396. X
  1397. X/*
  1398. X * The current word is unacceptable so erase it
  1399. X */
  1400. Xbadword()
  1401. X{
  1402. X
  1403. X    move(crow, ccol);
  1404. X    clrtoeol();
  1405. X    refresh();
  1406. X}
  1407. X
  1408. X/*
  1409. X * Highlight the nth word in the list (starting with word 0)
  1410. X * No check for wild arg
  1411. X */
  1412. Xshowword(n)
  1413. Xint n;
  1414. X{
  1415. X    int col, row;
  1416. X
  1417. X    row = LIST_LINE + n % (lastline - LIST_LINE + 1);
  1418. X    col = colstarts[n / (lastline - LIST_LINE + 1)];
  1419. X    move(row, col);
  1420. X    standout();
  1421. X    printw("%s", pword[n]);
  1422. X    standend();
  1423. X    move(crow, ccol);
  1424. X    refresh();
  1425. X    sleep(1);
  1426. X    move(row, col);
  1427. X    printw("%s", pword[n]);
  1428. X    move(crow, ccol);
  1429. X    refresh();
  1430. X}
  1431. X
  1432. X/*
  1433. X * Get a word from the user and check if it is in either of the two
  1434. X * word lists
  1435. X * If it's found, show the word on the board for a short time and then
  1436. X * erase the word
  1437. X *
  1438. X * Note: this function knows about the format of the board
  1439. X */
  1440. Xfindword()
  1441. X{
  1442. X    int c, col, found, i, r, row;
  1443. X    char buf[MAXWORDLEN + 1];
  1444. X    extern char board[];
  1445. X    extern int usedbits, wordpath[];
  1446. X    extern char *mword[], *pword[];
  1447. X    extern int nmwords, npwords;
  1448. X
  1449. X    getyx(stdscr, r, c);
  1450. X    getword(buf);
  1451. X    found = 0;
  1452. X    for (i = 0; i < npwords; i++) {
  1453. X        if (strcmp(buf, pword[i]) == 0) {
  1454. X            found = 1;
  1455. X            break;
  1456. X        }
  1457. X    }
  1458. X    if (!found) {
  1459. X        for (i = 0; i < nmwords; i++) {
  1460. X            if (strcmp(buf, mword[i]) == 0) {
  1461. X                found = 1;
  1462. X                break;
  1463. X            }
  1464. X        }
  1465. X    }
  1466. X    for (i = 0; i < MAXWORDLEN; i++)
  1467. X        wordpath[i] = -1;
  1468. X    usedbits = 0;
  1469. X    if (!found || checkword(buf, -1, wordpath) == -1) {
  1470. X        move(r, c);
  1471. X        clrtoeol();
  1472. X        addstr("[???]");
  1473. X        refresh();
  1474. X        sleep(1);
  1475. X        move(r, c);
  1476. X        clrtoeol();
  1477. X        refresh();
  1478. X        return;
  1479. X    }
  1480. X
  1481. X    standout();
  1482. X    for (i = 0; wordpath[i] != -1; i++) {
  1483. X        row = BOARD_LINE + (wordpath[i] / 4) * 2 + 1;
  1484. X        col = BOARD_COL + (wordpath[i] % 4) * 4 + 2;
  1485. X        move(row, col);
  1486. X        if (board[wordpath[i]] == 'q')
  1487. X            printw("Qu");
  1488. X        else
  1489. X            printw("%c", toupper(board[wordpath[i]]));
  1490. X        move(r, c);
  1491. X        refresh();
  1492. X        sleep(1);
  1493. X    }
  1494. X
  1495. X    standend();
  1496. X
  1497. X    for (i = 0; wordpath[i] != -1; i++) {
  1498. X        row = BOARD_LINE + (wordpath[i] / 4) * 2 + 1;
  1499. X        col = BOARD_COL + (wordpath[i] % 4) * 4 + 2;
  1500. X        move(row, col);
  1501. X        if (board[wordpath[i]] == 'q')
  1502. X            printw("Qu");
  1503. X        else
  1504. X            printw("%c", toupper(board[wordpath[i]]));
  1505. X    }
  1506. X    move(r, c);
  1507. X    clrtoeol();
  1508. X    refresh();
  1509. X}
  1510. X
  1511. X/*
  1512. X * Display a string at the current cursor position for the given number of secs
  1513. X */
  1514. Xshowstr(str, delay)
  1515. Xchar *str;
  1516. Xint delay;
  1517. X{
  1518. X
  1519. X    addstr(str);
  1520. X    refresh();
  1521. X    sleep(delay);
  1522. X    move(crow, ccol);
  1523. X    clrtoeol();
  1524. X    refresh();
  1525. X}
  1526. X
  1527. Xputstr(s)
  1528. Xchar *s;
  1529. X{
  1530. X
  1531. X    addstr(s);
  1532. X}
  1533. X
  1534. X/*
  1535. X * Get a valid word and put it in the buffer
  1536. X */
  1537. Xgetword(q)
  1538. Xchar *q;
  1539. X{
  1540. X    int ch, col, done, i, row;
  1541. X    char *p;
  1542. X
  1543. X    done = 0;
  1544. X    i = 0;
  1545. X    p = q;
  1546. X    addch('[');
  1547. X    refresh();
  1548. X    while (!done && i < MAXWORDLEN - 1) {
  1549. X        ch = getch() & 0177;
  1550. X        switch (ch) {
  1551. X        case '\177':            /* <del> */
  1552. X        case '\010':            /* <bs> */
  1553. X            if (p == q)
  1554. X                break;
  1555. X            p--;
  1556. X            getyx(stdscr, row, col);
  1557. X            move(row, col - 1);
  1558. X            clrtoeol();
  1559. X            break;
  1560. X        case '\025':            /* <^u> */
  1561. X        case '\027':            /* <^w> */
  1562. X            if (p == q)
  1563. X                break;
  1564. X            getyx(stdscr, row, col);
  1565. X            move(row, col - (int) (p - q));
  1566. X            p = q;
  1567. X            clrtoeol();
  1568. X            break;
  1569. X        case ' ':
  1570. X        case '\n':
  1571. X        case '\r':
  1572. X            done = 1;
  1573. X            break;
  1574. X        case '\014':            /* <^l> */
  1575. X        case '\022':            /* <^r> */
  1576. X            clearok(stdscr, 1);
  1577. X            refresh();
  1578. X            break;
  1579. X        default:
  1580. X            if (islower(ch)) {
  1581. X                *p++ = ch;
  1582. X                addch(ch);
  1583. X                i++;
  1584. X            }
  1585. X            break;
  1586. X        }
  1587. X        refresh();
  1588. X    }
  1589. X    *p = '\0';
  1590. X    addch(']');
  1591. X    refresh();
  1592. X}
  1593. X
  1594. Xshowboard(b)
  1595. Xchar *b;
  1596. X{
  1597. X
  1598. X    tty_showboard(b);
  1599. X}
  1600. X
  1601. Xprompt(mesg)
  1602. Xchar *mesg;
  1603. X{
  1604. X
  1605. X    move(PROMPT_LINE, PROMPT_COL);
  1606. X    printw("%s", mesg);
  1607. X    move(PROMPT_LINE + 1, PROMPT_COL);
  1608. X    refresh();
  1609. X}
  1610. X
  1611. Xrawch()
  1612. X{
  1613. X
  1614. X#ifdef TIMER
  1615. X    return(timerch());
  1616. X#else
  1617. X    return(getch() & 0177);
  1618. X#endif
  1619. X}
  1620. X
  1621. Xstatic
  1622. Xtty_setup()
  1623. X{
  1624. X#ifdef SIGTSTP
  1625. X    int stop_catcher(), cont_catcher();
  1626. X#endif
  1627. X#ifdef TIOCGWINSZ
  1628. X    int winch_catcher();
  1629. X#endif
  1630. X
  1631. X    initscr();
  1632. X    raw();
  1633. X    noecho();
  1634. X
  1635. X    /*
  1636. X     * Does curses look at the winsize structure?
  1637. X     * Should handle SIGWINCH ...
  1638. X     */
  1639. X    nlines = LINES;
  1640. X    lastline = nlines - 1;
  1641. X    ncols = COLS;
  1642. X
  1643. X#ifdef SIGTSTP
  1644. X    (void) signal(SIGTSTP, stop_catcher);
  1645. X    (void) signal(SIGCONT, cont_catcher);
  1646. X#endif   
  1647. X#ifdef TIOCGWINSZ
  1648. X    (void) signal(SIGWINCH, winch_catcher);
  1649. X#endif
  1650. X    return(0);
  1651. X}
  1652. X
  1653. X#ifdef SIGTSTP
  1654. Xstatic
  1655. Xstop_catcher()
  1656. X{
  1657. X
  1658. X    stoptime();
  1659. X    noraw();
  1660. X    echo();
  1661. X    move(nlines - 1, 0);
  1662. X    refresh();
  1663. X
  1664. X    (void) signal(SIGTSTP, SIG_DFL);
  1665. X#ifdef BSD42 
  1666. X    (void) sigsetmask(sigblock(0) & ~(1 << (SIGTSTP-1)));
  1667. X#endif
  1668. X    (void) kill(0, SIGTSTP);
  1669. X    (void) signal(SIGTSTP, stop_catcher);
  1670. X}
  1671. Xstatic
  1672. Xcont_catcher()
  1673. X{
  1674. X
  1675. X    (void) signal(SIGCONT, cont_catcher);
  1676. X    noecho();
  1677. X    raw();
  1678. X    clearok(stdscr, 1);
  1679. X    move(crow, ccol);
  1680. X    refresh();
  1681. X    starttime();
  1682. X}
  1683. X#endif SIGTSTP
  1684. X#ifdef SIGWINCH
  1685. X/*
  1686. X * The signal is caught but nothing is done about it...
  1687. X * It would mean reformatting the entire display
  1688. X */
  1689. Xstatic
  1690. Xwinch_catcher()
  1691. X{
  1692. X
  1693. X    struct winsize win;
  1694. X
  1695. X    (void) signal(SIGWINCH, winch_catcher);
  1696. X    (void) ioctl(fileno(stdout), TIOCGWINSZ, &win);
  1697. X    /*
  1698. X    LINES = win.ws_row;
  1699. X    COLS = win.ws_col;
  1700. X    */
  1701. X}
  1702. X#endif
  1703. X
  1704. Xstatic
  1705. Xtty_cleanup()
  1706. X{
  1707. X
  1708. X    move(nlines - 1, 0);
  1709. X    refresh();
  1710. X    noraw();
  1711. X    echo();
  1712. X    endwin();
  1713. X}
  1714. X
  1715. Xstatic
  1716. Xtty_showboard(b)
  1717. Xchar *b;
  1718. X{
  1719. X    register int i;
  1720. X    int line;
  1721. X
  1722. X    clear();
  1723. X    move(BOARD_LINE, BOARD_COL);
  1724. X    line = BOARD_LINE;
  1725. X    printw("+---+---+---+---+");
  1726. X    move(++line, BOARD_COL);
  1727. X    for (i = 0; i < 16; i++) {
  1728. X        if (b[i] == 'q')
  1729. X            printw("| Qu");
  1730. X        else
  1731. X            printw("| %c ", toupper(b[i]));
  1732. X        if ((i + 1) % 4 == 0) {
  1733. X            printw("|");
  1734. X            move(++line, BOARD_COL);
  1735. X            printw("+---+---+---+---+");
  1736. X            move(++line, BOARD_COL);
  1737. X        }
  1738. X    }
  1739. X    move(SCORE_LINE, SCORE_COL);
  1740. X    printw("Type '?' for help");
  1741. X    refresh();
  1742. X}
  1743. X
  1744. Xstatic
  1745. Xtty_prompt(p)
  1746. Xchar *p;
  1747. X{
  1748. X
  1749. X    move(PROMPT_LINE, PROMPT_COL);
  1750. X    printw("%s", p);
  1751. X    clrtoeol();
  1752. X    refresh();
  1753. X}
  1754. X
  1755. END_OF_mach.c
  1756. if test 10502 -ne `wc -c <mach.c`; then
  1757.     echo shar: \"mach.c\" unpacked with wrong size!
  1758. fi
  1759. # end of overwriting check
  1760. fi
  1761. if test -f mkdict.c -a "${1}" != "-c" ; then 
  1762.   echo shar: Will not over-write existing file \"mkdict.c\"
  1763. else
  1764. echo shar: Extracting \"mkdict.c\" \(1207 characters\)
  1765. sed "s/^X//" >mkdict.c <<'END_OF_mkdict.c'
  1766. X/* vi: set tabstop=4 : */
  1767. X
  1768. X/*
  1769. X * Filter out words that:
  1770. X *    1) Are not completely made up of lower case letters
  1771. X *    2) Contain a 'q' not immediately followed by a 'u'
  1772. X *    3) Are less that 3 characters long
  1773. X *    4) Are greater than MAXWORDLEN characters long
  1774. X */
  1775. X
  1776. X#include <ctype.h>
  1777. X#include <stdio.h>
  1778. X
  1779. X#include "bog.h"
  1780. X
  1781. Xmain(argc, argv)
  1782. Xint argc;
  1783. Xchar **argv;
  1784. X{
  1785. X    register char *p, *q, *r;
  1786. X    register int ch, common, i, n;
  1787. X    int current, len, prev, qcount;
  1788. X    char buf[2][MAXWORDLEN + 1];
  1789. X
  1790. X    prev = 0;
  1791. X    current = 1;
  1792. X    buf[prev][0] = '\0';
  1793. X    if (argc == 2)
  1794. X        n = atoi(argv[1]);
  1795. X    i = 1;
  1796. X    while (gets(buf[current]) != (char *) NULL) {
  1797. X        if (argc == 2 && i++ % n)
  1798. X            continue;
  1799. X        len = 0;
  1800. X        for (p = buf[current]; *p != '\0'; p++) {
  1801. X            if (!islower(*p))
  1802. X                break;
  1803. X            if (*p == 'q') {
  1804. X                q = p + 1;
  1805. X                if (*q != 'u')
  1806. X                    break;
  1807. X                else {
  1808. X                    while (*q = *(q + 1))
  1809. X                        q++;
  1810. X                }
  1811. X                len++;
  1812. X            }
  1813. X            len++;
  1814. X        }
  1815. X        if (*p != '\0' || len < 3 || len > MAXWORDLEN)
  1816. X            continue;
  1817. X
  1818. X        p = buf[current];
  1819. X        q = buf[prev];
  1820. X        qcount = 0;
  1821. X        while ((ch = *p++) == *q++ && ch != '\0')
  1822. X            if (ch == 'q')
  1823. X                qcount++;
  1824. X        common = p - buf[current] - 1;
  1825. X        printf("%c%s", common + qcount, p - 1);
  1826. X        prev = !prev;
  1827. X        current = !current;
  1828. X    }
  1829. X}
  1830. X
  1831. END_OF_mkdict.c
  1832. if test 1207 -ne `wc -c <mkdict.c`; then
  1833.     echo shar: \"mkdict.c\" unpacked with wrong size!
  1834. fi
  1835. # end of overwriting check
  1836. fi
  1837. if test -f mkindex.c -a "${1}" != "-c" ; then 
  1838.   echo shar: Will not over-write existing file \"mkindex.c\"
  1839. else
  1840. echo shar: Extracting \"mkindex.c\" \(1377 characters\)
  1841. sed "s/^X//" >mkindex.c <<'END_OF_mkindex.c'
  1842. X/* vi: set tabstop=4 : */
  1843. X
  1844. X#include <stdio.h>
  1845. X
  1846. X#include "bog.h"
  1847. X
  1848. Xmain(argc, argv)
  1849. Xint argc;
  1850. Xchar **argv;
  1851. X{
  1852. X    int clen, rlen, prev;
  1853. X    long off, start;
  1854. X    char buf[MAXWORDLEN + 1], *p, *nextword();
  1855. X
  1856. X    prev = '\0';
  1857. X    off = start = 0L;
  1858. X    while (nextword(stdin, buf, &clen, &rlen) != (char *) NULL) {
  1859. X        if (*buf != prev) {
  1860. X            if (prev != '\0')
  1861. X                printf("%c %6ld %6ld\n", prev, start, off - 1);
  1862. X            prev = *buf;
  1863. X            start = off;
  1864. X        }
  1865. X        off += clen + 1;
  1866. X    }
  1867. X    printf("%c %6ld %6ld\n", prev, start, off - 1);
  1868. X}
  1869. X
  1870. X/*
  1871. X * Return the next word in the compressed dictionary in 'buffer' or
  1872. X * NULL on end-of-file
  1873. X * Also set clen to the length of the compressed word (for mkindex) and
  1874. X * rlen to the strlen() of the real word
  1875. X */
  1876. Xchar *
  1877. Xnextword(fp, buffer, clen, rlen)
  1878. XFILE *fp;
  1879. Xchar *buffer;
  1880. Xint *clen, *rlen;
  1881. X{
  1882. X    register int ch, pcount;
  1883. X    register char *p, *q;
  1884. X    static char buf[MAXWORDLEN + 1];
  1885. X    static int first = 1;
  1886. X    static int lastch = 0;
  1887. X
  1888. X       if (first) {
  1889. X        if ((pcount = getc(fp)) == EOF)
  1890. X            return((char *) NULL);
  1891. X        first = 0;
  1892. X    }
  1893. X    else if ((pcount = lastch) == EOF)
  1894. X        return((char *) NULL);
  1895. X
  1896. X    p = buf + (*clen = pcount);
  1897. X    while ((ch = getc(fp)) != EOF && ch >= 'a')
  1898. X            *p++ = ch;
  1899. X        lastch = ch;
  1900. X    *p = '\0';
  1901. X
  1902. X    *rlen = (int) (p - buf);
  1903. X    *clen = *rlen - *clen;
  1904. X
  1905. X    p = buf;
  1906. X    q = buffer;
  1907. X    while ((*q++ = *p) != '\0') {
  1908. X        if (*p++ == 'q')
  1909. X            *q++ = 'u';
  1910. X    }
  1911. X    return(buffer);
  1912. X}
  1913. END_OF_mkindex.c
  1914. if test 1377 -ne `wc -c <mkindex.c`; then
  1915.     echo shar: \"mkindex.c\" unpacked with wrong size!
  1916. fi
  1917. # end of overwriting check
  1918. fi
  1919. if test -f prtable.c -a "${1}" != "-c" ; then 
  1920.   echo shar: Will not over-write existing file \"prtable.c\"
  1921. else
  1922. echo shar: Extracting \"prtable.c\" \(2164 characters\)
  1923. sed "s/^X//" >prtable.c <<'END_OF_prtable.c'
  1924. X/* vi: set tabstop=4 : */
  1925. X
  1926. X#include <curses.h>
  1927. X
  1928. X#define NCOLS    5
  1929. X
  1930. X/*
  1931. X * Routine to print a table
  1932. X * Modified from 'ls.c' mods (BJB/83)
  1933. X * Arguments:
  1934. X *    base    - address of first entry
  1935. X *    num     - number of entries
  1936. X *    d_cols  - number of columns to use if > 0, "best" size if == 0
  1937. X *    width    - max line width if not zero
  1938. X *    prentry - address of the routine to call to print the string
  1939. X *    length  - address of the routine to call to determine the length
  1940. X *          of string to be printed 
  1941. X *
  1942. X * prtable and length are called with the the address of the base and
  1943. X * an index
  1944. X */
  1945. Xprtable(base, num, d_cols, width, prentry, length)
  1946. Xchar *base;
  1947. Xint num, d_cols;
  1948. Xint (*prentry)(), (*length)();
  1949. X{
  1950. X        register int c, j;
  1951. X        register int a, b, cols, loc, maxlen, nrows, z;
  1952. X    int col, row;
  1953. X
  1954. X        if (num == 0)
  1955. X                return;
  1956. X    maxlen = get_maxlen(base, num, length) + 1;
  1957. X    if (d_cols > 0)
  1958. X        cols = d_cols;
  1959. X    else
  1960. X        cols = width / maxlen;
  1961. X    if (cols == 0)
  1962. X        cols = NCOLS;
  1963. X        nrows = (num - 1) / cols + 1;
  1964. X        for (a = 1; a <= nrows; a++) {
  1965. X                b = c = z = loc = 0;
  1966. X                for (j = 0; j < num; j++) {
  1967. X                        c++;
  1968. X                        if (c >= a + b)
  1969. X                                break;
  1970. X                }
  1971. X                while (j < num) {
  1972. X                        (*prentry)(base, j);
  1973. X            loc += (*length)(base, j);
  1974. X                        z++;
  1975. X                        b += nrows;
  1976. X                        for (j++; j < num; j++) {
  1977. X                                c++;
  1978. X                                if (c >= a + b)
  1979. X                                        break;
  1980. X                        }
  1981. X                        if (j < num) {
  1982. X                                while (loc < z * maxlen) {
  1983. X                    addch(' ');
  1984. X                                        loc++;
  1985. X                                }
  1986. X            }
  1987. X                }
  1988. X        getyx(stdscr, row, col);
  1989. X        move(row + 1, 0);
  1990. X        }
  1991. X    refresh();
  1992. X}
  1993. X
  1994. Xstatic int
  1995. Xget_maxlen(base, num, length)
  1996. Xchar *base;
  1997. Xint num;
  1998. Xint (*length)();
  1999. X{
  2000. X    register int i, len, max;
  2001. X
  2002. X    max = (*length)(base, 0);
  2003. X    for (i = 0; i < num; i++) {
  2004. X        if ((len = (*length)(base, i)) > max)
  2005. X            max = len;
  2006. X    }
  2007. X    return(max);
  2008. X}
  2009. X
  2010. END_OF_prtable.c
  2011. if test 2164 -ne `wc -c <prtable.c`; then
  2012.     echo shar: \"prtable.c\" unpacked with wrong size!
  2013. fi
  2014. # end of overwriting check
  2015. fi
  2016. if test -f showdict.c -a "${1}" != "-c" ; then 
  2017.   echo shar: Will not over-write existing file \"showdict.c\"
  2018. else
  2019. echo shar: Extracting \"showdict.c\" \(264 characters\)
  2020. sed "s/^X//" >showdict.c <<'END_OF_showdict.c'
  2021. X/* vi: set tabstop=4 : */
  2022. X
  2023. X#include <stdio.h>
  2024. X
  2025. X#include "bog.h"
  2026. X
  2027. X/*BOGUS*/
  2028. Xstruct dictindex dictindex[1];
  2029. Xint wordlen;
  2030. X
  2031. Xmain(argc, argv)
  2032. Xint argc;
  2033. Xchar **argv;
  2034. X{
  2035. X    char *p;
  2036. X    char *nextword();
  2037. X
  2038. X    while ((p = nextword(stdin)) != (char *) NULL)
  2039. X        printf("%s\n", p);
  2040. X}
  2041. X
  2042. END_OF_showdict.c
  2043. if test 264 -ne `wc -c <showdict.c`; then
  2044.     echo shar: \"showdict.c\" unpacked with wrong size!
  2045. fi
  2046. # end of overwriting check
  2047. fi
  2048. if test -f timer.c -a "${1}" != "-c" ; then 
  2049.   echo shar: Will not over-write existing file \"timer.c\"
  2050. else
  2051. echo shar: Extracting \"timer.c\" \(1799 characters\)
  2052. sed "s/^X//" >timer.c <<'END_OF_timer.c'
  2053. X/* vi: set tabstop=4 : */
  2054. X
  2055. X#include "bog.h"
  2056. X
  2057. X#ifdef TIMER
  2058. X
  2059. X#include <setjmp.h>
  2060. X#include <curses.h>
  2061. X#include <stdio.h>
  2062. X
  2063. X/*
  2064. X * Update the display of the remaining time while waiting for a character
  2065. X * If time runs out do a longjmp() to the game controlling routine, returning
  2066. X * non-zero; oth. return the character
  2067. X * Leave the cursor where it was initially
  2068. X */
  2069. Xtimerch()
  2070. X{
  2071. X    int col, remaining, row;
  2072. X    long prevt, t;
  2073. X    extern int tlimit;
  2074. X    extern long start_t;
  2075. X    extern jmp_buf env;
  2076. X
  2077. X    getyx(stdscr, row, col);
  2078. X    prevt = 0L;
  2079. X    while (1) {
  2080. X        if (waitch(1000L) == 1)
  2081. X            break;
  2082. X        time(&t);
  2083. X        if (t == prevt)
  2084. X            continue;
  2085. X        prevt = t;
  2086. X        remaining = tlimit - (int) (t - start_t);
  2087. X        if (remaining < 0) {
  2088. X            longjmp(env, 1);
  2089. X            /*NOTREACHED*/
  2090. X        }
  2091. X        move(TIMER_LINE, TIMER_COL);
  2092. X        printw("%d:%02d", remaining / 60, remaining % 60);
  2093. X        move(row, col);
  2094. X        refresh();
  2095. X    }
  2096. X    return(getch() & 0177);
  2097. X}
  2098. X
  2099. X/*
  2100. X * Wait up to 'delay' microseconds for input to appear
  2101. X * Returns 1 if input is ready, 0 oth.
  2102. X */
  2103. X
  2104. X#ifdef BSD42
  2105. X
  2106. X#include <sys/time.h>
  2107. X
  2108. Xstatic
  2109. Xwaitch(delay)
  2110. Xlong delay;
  2111. X{
  2112. X    int fdbits;
  2113. X    struct timeval duration;
  2114. X
  2115. X    duration.tv_sec = 0L;
  2116. X    duration.tv_usec = delay;
  2117. X    fdbits = 1;
  2118. X    return(select(32, &fdbits, 0, 0, &duration));
  2119. X}
  2120. X#endif BSD42
  2121. X
  2122. X#ifdef SYSV
  2123. X
  2124. X#include <sys/ioctl.h>
  2125. X
  2126. X/*
  2127. X * This is not too efficient...
  2128. X */
  2129. Xstatic
  2130. Xwaitch(delay)
  2131. Xlong delay;
  2132. X{
  2133. X    int nchars;
  2134. X
  2135. X    if (ioctl(fileno(stdin), FIONREAD, &nchars) < 0) {
  2136. X        perror("ioctl():");
  2137. X        cleanup();
  2138. X        exit(1);
  2139. X    }
  2140. X    return(nchars > 0);
  2141. X}
  2142. X#endif SYSV
  2143. X
  2144. X#ifdef ATARI
  2145. X
  2146. X#include <osbind.h>
  2147. X
  2148. X/*
  2149. X * The ST curses turns on the cursor only when a read is performed
  2150. X * Since there's nothing better to do at this point the cursor can
  2151. X * be enabled
  2152. X */
  2153. Xstatic
  2154. Xwaitch(delay)
  2155. Xlong delay;
  2156. X{
  2157. X
  2158. X    Bconout(2, '\033');
  2159. X    Bconout(2, 'e');
  2160. X    return(Cconis() == -1);
  2161. X}
  2162. X#endif ATARI
  2163. X
  2164. X#endif TIMER
  2165. X
  2166. END_OF_timer.c
  2167. if test 1799 -ne `wc -c <timer.c`; then
  2168.     echo shar: \"timer.c\" unpacked with wrong size!
  2169. fi
  2170. # end of overwriting check
  2171. fi
  2172. if test -f word.c -a "${1}" != "-c" ; then 
  2173.   echo shar: Will not over-write existing file \"word.c\"
  2174. else
  2175. echo shar: Extracting \"word.c\" \(3450 characters\)
  2176. sed "s/^X//" >word.c <<'END_OF_word.c'
  2177. X/* vi: set tabstop=4 : */
  2178. X
  2179. X#include <stdio.h>
  2180. X
  2181. X#include "bog.h"
  2182. X
  2183. X#ifdef ATARI
  2184. X#include <stat.h>
  2185. X#include <osbind.h>
  2186. X#define malloc(x)       Malloc(x)
  2187. X#else
  2188. X#include <sys/types.h>
  2189. X#include <sys/stat.h>
  2190. X#endif
  2191. X
  2192. Xstatic char *dictspace, *dictend;
  2193. Xstatic char *sp;
  2194. X
  2195. Xstatic int first = 1, lastch = 0;
  2196. X
  2197. X/*
  2198. X * Return the next word in the compressed dictionary in 'buffer' or
  2199. X * NULL on end-of-file
  2200. X */
  2201. Xchar *
  2202. Xnextword(fp)
  2203. XFILE *fp;
  2204. X{
  2205. X    register int ch, pcount;
  2206. X    register char *p;
  2207. X    static char buf[MAXWORDLEN + 1];
  2208. X    extern int wordlen;
  2209. X
  2210. X    if (fp == (FILE *) NULL) {
  2211. X        if (sp == dictend)
  2212. X            return((char *) NULL);
  2213. X
  2214. X        p = buf + (int) *sp++;
  2215. X
  2216. X        /*
  2217. X         * The dictionary ends with a null byte
  2218. X         */
  2219. X        while (*sp >= 'a') {
  2220. X            if ((*p++ = *sp++) == 'q')
  2221. X                *p++ = 'u';
  2222. X        }
  2223. X    }
  2224. X    else {
  2225. X        if (first) {
  2226. X            if ((pcount = getc(fp)) == EOF)
  2227. X                return((char *) NULL);
  2228. X            first = 0;
  2229. X        }
  2230. X        else if ((pcount = lastch) == EOF)
  2231. X            return((char *) NULL);
  2232. X
  2233. X        p = buf + pcount;
  2234. X        while ((ch = getc(fp)) != EOF && ch >= 'a') {
  2235. X            if ((*p++ = ch) == 'q')
  2236. X                *p++ = 'u';
  2237. X        }
  2238. X        lastch = ch;
  2239. X    }
  2240. X    wordlen = (int) (p - buf);
  2241. X    *p = '\0';
  2242. X    return(buf);
  2243. X}
  2244. X/*
  2245. X * Reset the state of nextword() and do the fseek()
  2246. X */
  2247. Xdictseek(fp, offset, ptrname)
  2248. XFILE *fp;
  2249. Xlong offset;
  2250. Xint ptrname;
  2251. X{
  2252. X
  2253. X    if (fp == (FILE *) NULL) {
  2254. X        if ((sp = dictspace + offset) >= dictend)
  2255. X            return(-1);
  2256. X        return(0);
  2257. X    }
  2258. X
  2259. X    first = 1;
  2260. X    return(fseek(fp, offset, ptrname));
  2261. X}
  2262. X
  2263. XFILE *
  2264. Xopendict(dict)
  2265. Xchar *dict;
  2266. X{
  2267. X    FILE *fp;
  2268. X
  2269. X#ifdef ATARI
  2270. X    if ((fp = fopen(dict, "rb")) == (FILE *) NULL)
  2271. X        return((FILE *) NULL);
  2272. X#else
  2273. X    if ((fp = fopen(dict, "r")) == (FILE *) NULL)
  2274. X        return((FILE *) NULL);
  2275. X#endif
  2276. X    return(fp);
  2277. X}
  2278. X
  2279. X/*
  2280. X * Load the given dictionary and initialize the pointers
  2281. X */
  2282. Xloaddict(fp)
  2283. XFILE *fp;
  2284. X{
  2285. X    int st;
  2286. X    char *p;
  2287. X    long n;
  2288. X    struct stat statb;
  2289. X
  2290. X#ifdef ATARI
  2291. X    if (stat(DICT, &statb) < 0) {
  2292. X        (void) fclose(fp);
  2293. X        return(-1);
  2294. X    }
  2295. X#else
  2296. X    char *malloc();
  2297. X
  2298. X    if (fstat(fileno(fp), &statb) < 0) {
  2299. X        (void) fclose(fp);
  2300. X        return(-1);
  2301. X    }
  2302. X#endif
  2303. X
  2304. X    /*
  2305. X     * An extra character (a sentinel) is allocated and set to null to improve
  2306. X     * the expansion loop in nextword()
  2307. X     */
  2308. X    if ((dictspace = (char *) malloc(statb.st_size + 1)) == (char *) NULL) {
  2309. X        (void) fclose(fp);
  2310. X        return(-1);
  2311. X    }
  2312. X    n = (long) statb.st_size;
  2313. X    sp = dictspace;
  2314. X    dictend = dictspace + n;
  2315. X
  2316. X    p = dictspace;
  2317. X    while (n > 0 && (st = fread(p, 1, BUFSIZ, fp)) > 0) {
  2318. X        p += st;
  2319. X        n -= st;
  2320. X    }
  2321. X    if (st < 0) {
  2322. X        (void) fclose(fp);
  2323. X        (void) fprintf(stderr, "Error reading dictionary\n");
  2324. X        return(-1);
  2325. X    }
  2326. X    *p = '\0';
  2327. X    return(0);
  2328. X}
  2329. X
  2330. X/*
  2331. X * Dependent on the exact format of the index file:
  2332. X * Starting offset field begins in column 1 and length field in column 9
  2333. X */
  2334. Xloadindex(indexfile)
  2335. Xchar *indexfile;
  2336. X{
  2337. X    register int i, j;
  2338. X    char buf[MAXWORDLEN + 1];
  2339. X    FILE *fp;
  2340. X    long atol();
  2341. X    extern struct dictindex dictindex[];
  2342. X    if ((fp = fopen(indexfile, "r")) == (FILE *) NULL) {
  2343. X        (void) fprintf(stderr, "Can't open '%s'\n", indexfile);
  2344. X        return(-1);
  2345. X    }
  2346. X    i = 0;
  2347. X    while (fgets(buf, sizeof(buf), fp) != (char *) NULL) {
  2348. X        j = *buf - 'a';
  2349. X        if (i != j) {
  2350. X            (void) fprintf(stderr, "Bad index order\n");
  2351. X            return(-1);
  2352. X        }
  2353. X        dictindex[j].start = atol(buf + 1);
  2354. X        dictindex[j].length = atol(buf + 9) - dictindex[j].start;
  2355. X        i++;
  2356. X    }
  2357. X    if (i != 26) {
  2358. X        (void) fprintf(stderr, "Bad index length\n");
  2359. X        return(-1);
  2360. X    }
  2361. X    (void) fclose(fp);
  2362. X    return(0);
  2363. X} 
  2364. END_OF_word.c
  2365. if test 3450 -ne `wc -c <word.c`; then
  2366.     echo shar: \"word.c\" unpacked with wrong size!
  2367. fi
  2368. # end of overwriting check
  2369. fi
  2370. if test -f helpfile -a "${1}" != "-c" ; then 
  2371.   echo shar: Will not over-write existing file \"helpfile\"
  2372. else
  2373. echo shar: Extracting \"helpfile\" \(3620 characters\)
  2374. sed "s/^X//" >helpfile <<'END_OF_helpfile'
  2375. X
  2376. XCommands:
  2377. X
  2378. XEnter word:                 <return> or <linefeed> or <space>
  2379. XDelete previous character:  <delete> or <backspace>
  2380. XDelete line:                <^u> or <^w>
  2381. XRedraw screen:              <^l> or <^r>
  2382. XPause game:                 <^s>
  2383. XResume game:                <^q> or <^s>
  2384. XSuspend game (BSD only):    <^z>
  2385. XGive up on current cube:    <^d>
  2386. XShow remaining time:        <space> first thing on a line
  2387. XShow help:                  ? (Suspends timer until done)
  2388. XExit game:                  <^c>
  2389. X
  2390. X(^u means "control u", etc.)
  2391. X
  2392. X[Note for users of versions of this program that do not display a timer:
  2393. XThe first word entered after the timer has run out causes a list of all the
  2394. Xwords you found, the words you missed, and your running statistics to be
  2395. Xdisplayed.]
  2396. X
  2397. XAny time you are prompted while the board is displayed you can type:
  2398. X                           <esc>word
  2399. Xto see where "word" is on the board.
  2400. X
  2401. XUsage:
  2402. X    bog [-b] [-d] [-s#] [-t#] [-w#] [+[+]] [boardspec]
  2403. X
  2404. X    -b: batch mode (boardspec must be present); dictionary read from stdin
  2405. X    -d: debug mode
  2406. X    -s#: use # as the random number seed
  2407. X    -t#: time limit is # seconds instead of default 180
  2408. X    -w#: minimum word length is # letters instead of default 3
  2409. X    +: can reuse a cube, but not twice in succession
  2410. X    ++: can reuse cubes arbitrarily
  2411. X    boardspec: the first board to use (use 'q' for 'qu'); e.g.:
  2412. X          bog nolezeebnqieegei
  2413. X.
  2414. X                            Default Rules
  2415. X
  2416. XA Boggle board is a four by four arrangement of Boggle cubes.
  2417. XYou have 3 minutes to find as many words as possible in the Boggle board.
  2418. XWords are formed by finding a sequence of cubes (letters) that are in the
  2419. Xgame's dictionary.  The (N+1)th cube in the word must be horizontally,
  2420. Xvertically, or diagonally adjacent to the Nth cube.  Cubes cannot be reused.
  2421. XWords consist solely of lower case letters and must be at least 3 letters long.
  2422. X.
  2423. X                           Options
  2424. X
  2425. XCommand line flags can be given to change the rules of the game.
  2426. XThe '+' flag allows a cube to be used multiple times, but not in succession.
  2427. XThe '++' flag allows the same cubes to be considered adjacent to itself.
  2428. XThe time limit can be changed from the default 3 minutes by using the flag
  2429. X'-t#', where # is the duration (in seconds) of each game.
  2430. XThe minimum word length can be changed from 3 letters by specifying 'w#',
  2431. Xwhere # is the minimum number of letters to use.
  2432. X.
  2433. X                           Bugs and Limitations
  2434. X
  2435. XThe following bugs and problems are known to exist:
  2436. X
  2437. X- If there are a great many words in the cube the final display of the words
  2438. X  may scroll off of the screen.  (On a 25 line screen about 130 words can be
  2439. X  displayed.)
  2440. X
  2441. X- Computing the complete word list can be too slow on small machines.
  2442. X
  2443. X- No word can contain a 'q' that is not immediately followed by a 'u'.
  2444. X
  2445. X- When using the '+' or '++' options the display of words found in the board
  2446. X  doesn't indicate reused cubes.
  2447. X.
  2448. X                           About This Program
  2449. X
  2450. XPermission is given to freely copy and distribute this software providing:
  2451. X
  2452. X1) You do not sell it,
  2453. X2) You do not use it for commercial advantage,
  2454. X3) If you pass the program on you must make the source code available, and
  2455. X4) This notice must accompany the distribution
  2456. X
  2457. XPlease notify the author of any bugs or if you have any suggestions.
  2458. X
  2459. XCopyright (c) 1988:
  2460. XBarry Brachman
  2461. XDept. of Computer Science
  2462. XUniv. of British Columbia
  2463. XVancouver, B.C. V6T 1W5
  2464. X
  2465. X.. {ihnp4!alberta, uw-beaver, uunet}!ubc-vision!ubc-csgrads!brachman
  2466. Xbrachman@grads.cs.ubc.cdn
  2467. Xbrachman%ubc.csnet@csnet-relay.arpa
  2468. Xbrachman@ubc.csnet
  2469. X
  2470. XBoggle is a trademark of Parker Brothers.
  2471. X
  2472. END_OF_helpfile
  2473. if test 3620 -ne `wc -c <helpfile`; then
  2474.     echo shar: \"helpfile\" unpacked with wrong size!
  2475. fi
  2476. # end of overwriting check
  2477. fi
  2478. echo shar: End of shell archive.
  2479. exit 0
  2480.